﻿using EasyI18n.Api.Infrastructure.DataPersistence.MongoDb;
using EasyI18n.Api.Infrastructure.DataPersistence.MongoDb.Entities;
using EasyI18n.Api.Infrastructure.JwtFunction;
using EasyI18n.Api.Primary.Contracts.Bases;
using EasyI18n.Api.Primary.Contracts.Users;
using EasyI18n.Api.Realization.Bases;
using FluentValidation;
using Mediator.Net.Context;
using MongoDB.Driver;
using Shouldly;


namespace EasyI18n.Api.Realization.Handlers.Users;

public class LoginHandler(
    IDocumentAccessor<SystemUser> systemUsersDocs,
    IDocumentAccessor<SystemUserLogin> systemUserLoginsDocs,
    IPasswordHasher passwordHasher,
    JwtService jwtService  
    ): ILoginContract
{
    public void Validate(ContractValidator<LoginCommand> validator)
    {
        validator.RuleFor(e => e.UserName)
            .NotEmpty();

        validator.RuleFor(e => e.Password)
            .NotEmpty();
    }

    public void Test(TestContext<LoginCommand, LoginResponse> context)
    {
        var exceptionUserCase = context.CreateTestCase();
        exceptionUserCase.Message = new LoginCommand().Faker();
        exceptionUserCase.Assert = result =>
        {
            var exception = result.Exception as BusinessException;
            result.Exception.ShouldNotBeNull();
            exception.Type.ShouldBe(BusinessExceptionTypeEnum.DataNotExists);
            return Task.CompletedTask;
        };
        
        var userCase = context.CreateTestCase();
        userCase.Arrange = async () =>
        {
            var user = new SystemUser()
            {
                UserName = "BILLIE.L",
                PasswordHash = passwordHasher.HashPasswordV3("123456"),
            };
            await systemUsersDocs.Collection.InsertOneAsync(user);
        };
        userCase.Message = new LoginCommand()
        {
            UserName = "BILLIE.L",
            Password = "123456"
        };
        userCase.Assert = result =>
        {
            result.Exception.ShouldBeNull();
            return Task.CompletedTask;;
        };
    }

    public async Task<LoginResponse> Handle(IReceiveContext<LoginCommand> context, CancellationToken cancellationToken)
    {
        // 使用 FindAsync 查找用户
        var userCursor = await systemUsersDocs.Collection.FindAsync(x=>x.UserName == context.Message.UserName, cancellationToken: cancellationToken);
        var userList = await userCursor.ToListAsync(cancellationToken); // 将游标转换为列表

        var user = userList.SingleOrDefault(); // 获取第一个用户（如果存在）

        if (user == null)
        {
            throw new BusinessException("用户不存在，请注册。", BusinessExceptionTypeEnum.DataNotExists);
        }

        // 验证密码
        if (!passwordHasher.VerifyHashedPasswordV3(user.PasswordHash, context.Message.Password))
        {
            throw new BusinessException("用户名或密码错误", BusinessExceptionTypeEnum.UnauthorizedIdentity);
        }

        // 生成 JWT 令牌
        var token = jwtService.GenerateAccessJwtToken(user.Id.ToString());
        var refreshToken = jwtService.GenerateRefreshJwtToken(token.Token);

        // todo 新增 登录记录 - systemUserLogin 
        var userlogin = new SystemUserLogin()
        {
            LoginProvider = "EasyI18n.Api",
            ProviderKey = user.Id.ToString(),
            ProviderDisplayName = "EasyI18n.Api",
            UserId = user.Id
        };
        await systemUserLoginsDocs.Collection.InsertOneAsync(userlogin, cancellationToken: cancellationToken);
        
        return new LoginResponse
        {
            AccessToken = token.Token,
            RefreshToken = refreshToken.Token
        };
      
    }
}